package com.autumn.util;

import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Predicate;

/**
 * 集合帮助
 * 
 * @author 老码农
 *
 *         2017-10-27 15:40:42
 */
public class CollectionUtils {

	/**
	 * 转为数组
	 * 
	 * @param collection    集合
	 * @param componentType 类型
	 * @return 返回新的数组
	 *
	 */
	public static <E> E[] toArray(Collection<E> collection, Class<E> componentType) {
		return toArray(collection, componentType, null);
	}

	/**
	 * 转为数组
	 * 
	 * @param collection    集合
	 * @param componentType 类型
	 * @param predicate     条件
	 * @return 返回新的数组
	 *
	 */
	@SuppressWarnings("unchecked")
	public static <E> E[] toArray(Collection<E> collection, Class<E> componentType, Predicate<E> predicate) {
		ExceptionUtils.checkNotNull(componentType, "componentType");
		if (collection == null) {
			return null;
		}
		Collection<E> items = collection;
		if (predicate != null) {
			List<E> newItems = new ArrayList<E>();
			for (E item : collection) {
				if (predicate.test(item)) {
					newItems.add(item);
				}
			}
			items = newItems;
		}
		E[] array = (E[]) Array.newInstance(componentType, items.size());
		int i = 0;
		for (E item : items) {
			array[i] = item;
			i++;
		}
		return array;
	}

	/**
	 * 计算集合大小
	 * 
	 * @param collection 集合
	 * @param predicate  条件
	 * @return
	 */
	public static <E> int count(Collection<E> collection, Predicate<E> predicate) {
		ExceptionUtils.checkNotNull(collection, "collection");
		ExceptionUtils.checkNotNull(predicate, "predicate");
		int count = 0;
		for (E item : collection) {
			if (predicate.test(item)) {
				count++;
			}
		}
		return count;
	}

	/**
	 * 移除符合条件的集合
	 * 
	 * @param collection
	 * @param predicate
	 * @return
	 */
	public static <E> void removeBypredicate(Collection<E> collection, Predicate<E> predicate) {
		ExceptionUtils.checkNotNull(collection, "collection");
		ExceptionUtils.checkNotNull(predicate, "predicate");
		Iterator<E> iterator = collection.iterator();
		while (iterator.hasNext()) {
			E e = iterator.next();
			if (predicate.test(e)) {
				iterator.remove();
			}
		}
	}

	/**
	 * 查找符合条件并返回新的集合
	 * 
	 * @param collection 集合
	 * @param predicate  条件
	 * @return
	 */
	public static <E> List<E> findCollection(Collection<E> collection, Predicate<E> predicate) {
		ExceptionUtils.checkNotNull(collection, "collection");
		ExceptionUtils.checkNotNull(predicate, "predicate");
		List<E> items = new ArrayList<E>();
		Iterator<E> iterator = collection.iterator();
		while (iterator.hasNext()) {
			E e = iterator.next();
			if (predicate.test(e)) {
				items.add(e);
			}
		}
		return items;
	}

	/**
	 * 所有元素是否都满足条件,若全部满足则
	 * 
	 * @param collection 集合
	 * @param predicate  条件
	 * @return
	 */
	public static <E> boolean all(Collection<E> collection, Predicate<E> predicate) {
		return count(collection, predicate) == collection.size();
	}

	/**
	 * 是否有一个以上元素满足条件
	 * 
	 * @param collection 集合
	 * @param predicate  条件
	 * @return
	 */
	public static <E> boolean any(Collection<E> collection, Predicate<E> predicate) {
		ExceptionUtils.checkNotNull(collection, "collection");
		ExceptionUtils.checkNotNull(predicate, "predicate");
		for (E item : collection) {
			if (predicate.test(item)) {
				return true;
			}
		}
		return false;
	}

	/**
	 * 集合循环处理
	 * 
	 * @param collection 集合
	 * @param action     动作
	 */
	public static <E> void forHandle(Collection<E> collection, Consumer<E> action) {
		if (collection == null) {
			return;
		}
		if (action == null) {
			return;
		}
		for (E item : collection) {
			action.accept(item);
		}
	}

	/**
	 * 集合循环处理
	 * 
	 * @param collection 集合
	 * @param action     动作
	 * @param predicate  条件
	 */
	public static <E> void forHandle(Collection<E> collection, Consumer<E> action, Predicate<E> predicate) {
		if (collection == null) {
			return;
		}
		if (action == null) {
			return;
		}
		if (predicate != null) {
			for (E item : collection) {
				if (predicate.test(item)) {
					action.accept(item);
				}
			}
		} else {
			for (E item : collection) {
				action.accept(item);
			}
		}
	}
}
